package org.janon.httpproxy;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Log
{
	private boolean isWriteToScream;
	private List<OutputStream> osList = null;
	private static Log clientLog = null;
	private boolean isRecordToFile = false;
	private int threadNum = 0;
	private static DateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

	public synchronized void addThread()
	{
		threadNum++;
	}

	public synchronized void delThread()
	{
		threadNum--;
	}

	private Log()
	{
		osList = new ArrayList<OutputStream>();
		setWriteToScream(true);
	}

	public static Log getInstance()
	{
		if (clientLog == null)
		{
			clientLog = new Log();
		}
		return clientLog;
	}

	public synchronized RequestLogStream writeLog(HttpModel httpModel)
	{
		String s = String.format("%-10s %-8s %s %s", httpModel.getHttpType(), httpModel.getMethodString(), httpModel.getUserAddr(), httpModel
				.getUrl().getUrl());
		String date = dataFormat.format(new Date());
		for (OutputStream os : osList)
		{
			try
			{
				os.write(String.format("%-23s %s", date, s + HttpUtil.CRLF).getBytes());
				os.flush();
			}
			catch (Exception e)
			{
			}
		}
		if (isRecordToFile() && s.indexOf("HTTP") == 0)
		{
			String fn = (date + " " + httpModel.getMethodString() + " " + httpModel.getUrl().getHost() + " -.txt")
					.replaceAll("[/\\:*\"?|<>]", " ");
			OutputStream os = null;
			OutputStream is = null;
			try
			{
				os = new FileOutputStream(new File(fn));
			}
			catch (Exception e)
			{
				os = null;
			}
			fn = (date + " " + httpModel.getMethodString() + " " + httpModel.getUrl().getHost() + " +.txt")
			.replaceAll("[/\\:*\"?|<>]", " ");
			try
			{
				is = new FileOutputStream(new File(fn));
			}
			catch (Exception e)
			{
				is = null;
			}
			return new RequestLogStream(os,is);
		}
		else {
			return new RequestLogStream(null,null);
		}
	}

	public synchronized OutputStream writeLog(String s)
	{
		String date = dataFormat.format(new Date());
		for (OutputStream os : osList)
		{
			try
			{
				os.write(String.format("%-23s %s", date, s + HttpUtil.CRLF).getBytes());
				os.flush();
			}
			catch (Exception e)
			{
			}
		}
		if (isRecordToFile() && s.indexOf("HTTP") == 0)
		{
			String fn = (date + " " + s + ".txt").replaceAll("[/\\:*\"?|<>]", " ");
			try
			{
				return new FileOutputStream(new File(fn));
			}
			catch (Exception e)
			{
				return null;
			}
		}
		return null;
	}

	public boolean isWriteToScream()
	{
		return isWriteToScream;
	}

	public synchronized void addRecordLog(OutputStream os)
	{
		if (!osList.contains(os))
		{
			osList.add(os);
		}
	}

	public synchronized void removeRecordLog(OutputStream os)
	{
		if (osList.contains(os))
		{
			osList.remove(os);
		}
	}

	public void setWriteToScream(boolean isWriteToScream)
	{
		if (isWriteToScream)
		{
			if (!osList.contains(System.out))
			{
				osList.add(System.out);
			}
		}
		else
		{
			if (osList.contains(System.out))
			{
				osList.remove(System.out);
			}
		}
		this.isWriteToScream = isWriteToScream;
	}

	public boolean isRecordToFile()
	{
		return isRecordToFile;
	}

	public void setRecordToFile(boolean isRecordToFile)
	{
		this.isRecordToFile = isRecordToFile;
	}

	public void writeRecordToFile(OutputStream os, String s)
	{
		try
		{
			os.write((s + HttpUtil.CRLF).getBytes());
			os.flush();
		}
		catch (Exception e)
		{
		}
	}

	public void writeRecordToFile(OutputStream os, byte[] s, int begin, int end)
	{
		try
		{
			os.write(s, begin, end);
			os.flush();
		}
		catch (Exception e)
		{
		}
	}

	public int getThreadNum()
	{
		return threadNum;
	}
}
